package cargarDatos;

import java.awt.Point;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 *
 * @author civilian
 */
public class CargaDatos {

    int ofEstudiante;//TODO: faltaria meter los offset a todas las tablas pero 
                    //no es necesario solo da mas velocidad
    Iteradores its;
    ConexionBD insertarBD;
    int offsetProgAcademico;
    //TODO:aplicar lo de configurar la conexion  a estos parametros
    String url = "jdbc:postgresql://localhost:5432/DataMartAcademico",
            usuario = "postgres",
            pasword = "postgres";

    static void dbg(Object... o) {
        System.out.println(Arrays.deepToString(o));
    }

    public CargaDatos() {
    }

    ConexionBD conectarBD() {
        try {
            //TODO: depronto implementar singlenton aca para memoria y posible desempeño
            ConexionBD con = new ConexionBD(url, usuario, pasword);
            con.st = con.conexion.createStatement();
            return con;
        } catch (SQLException ex) {
            Logger.getLogger(CargaDatos.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public static void main(String[] args) throws SQLException, Throwable {
        CargaDatos ob = new CargaDatos();
        ob.cargarDatos();
    }

    public boolean cargarDatos() throws SQLException, Throwable {
        reiniciar();

        dbg("hora");
        cargarHora();//
        dbg("fecha");
        cargarFecha();//

        dbg("estudiante");
        cargarEstudiante();//
        dbg("programa");
        cargaProgramaAcademico();//
        dbg("demografico");
        cargarDemografico();//
        dbg("asignatura");
        cargarAsignatura();//
        dbg("locacion");
        cargarLocacion();//
        dbg("matricula");
        cargarMatriculaYCancelaciones();
        
        finalize();
        return false;
    }

    private void cargarHora() {
        insertarBD = conectarBD();
        try {
            BufferInsert insert = new BufferInsert(insertarBD.st, "INSERT INTO hora "
                    + "(hora_k,jornada,franja,"
                    + "hora) VALUES ");
            for (int i = 7; i < 25; i++) {
                insert.append(generarDatosHoraNumero(i));
            }
//            dbg(insert.toString());
            insert.flush();
        } catch (SQLException ex) {
            Logger.getLogger(CargaDatos.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private String generarDatosHoraNumero(int i) {
        return String.format("(DEFAULT, '%s', '%s', %d)", jornada(i), franja(i, 3, 7), i);
    }

    private String jornada(int i) {
        if (i >= 1 && i <= 12) {
            return "mañana";
        }
        if (i >= 13 && i <= 18) {
            return "tarde";
        } else {
            return "noche";
        }
    }

    private String franja(int i, int tamFranja, int inicioFranja) {
        StringBuilder salida = new StringBuilder();
        int op = i - inicioFranja;
        op = op / tamFranja;
        op = (tamFranja * op) + inicioFranja;
        salida.append(op);
        salida.append("-");
        //TODO: la hora queda con la franja floor osea 13 queda 
        //con la franja 13-16, y se podria poner tambien con 10-13
        salida.append(op + tamFranja);
        return salida.toString();
    }

    private void cargarLocacion() {
        try {
            IteradorDatos iterador = its.getIterador("LOCACIONES", its.SQL, "");

            insertarBD = conectarBD();
            BufferInsert insert = new BufferInsert(insertarBD.st, "INSERT INTO LOCACION "
                    + "(locacion_k,facultad,escuela_instituto,"
                    + "edificio,espacio, numEquipos,ipEquipo) VALUES ");
            while (iterador.next()) {

                for (int i = 0; i < iterador.getInt(5)/*cantEquipos*/; i++) {
//                    dbg(generarDatosLocacionObj(iterador,i));
                    insert.append(generarDatosLocacionObj(iterador, i));
//                    dbg(insert.toString());
                }
            }
//            dbg(insert.toString());
            insert.flush();
        } catch (SQLException ex) {
            Logger.getLogger(CargaDatos.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private String generarDatosLocacionObj(IteradorDatos iterador, int equipo) throws SQLException {
        return String.format("(DEFAULT, '%s', '%s', '%s', '%s', %s, '%s')", iterador.getString(1), iterador.getString(2), iterador.getString(3), iterador.getString(4), iterador.getString(5), generarIp(equipo, iterador.getString(4)));
    }

    private String generarIp(int equipo, String espacio) {
//        dbg(espacio);
        if(Character.isLetter(espacio.charAt(0)))
            return String.format("%d.%d.%d.%d",randomInt(255) ,randomInt(255),randomInt(255),
                                            equipo);
        else
            return String.format("192.168.%s.%s", Integer.parseInt(espacio.substring(1, 4)),
                                            /*(Integer.parseInt(espacio.substring(0, 2))*100)+*/ equipo);
    }

    private void cargaProgramaAcademico() {
        try {
            offsetProgAcademico=offsetProgAcademico();
            IteradorDatos iterador = its.getIterador("PROGRAMAS", its.SQL, "");

            insertarBD = conectarBD();
            BufferInsert insert = new BufferInsert(insertarBD.st, "INSERT INTO PROGRAMA_ACADEMICO "
                    + "(programa_k,codigo,nombre,"
                    + "snies,duracionSemestres, totalCreditos,nivel_programa, "
                    + "acreditacion, enteQOfrece) VALUES "); 
            while (iterador.next()) {
//                dbg(generarDatosProgramasObj(iterador,offsetProgAcademico));
                insert.append(generarDatosProgramasObj(iterador, offsetProgAcademico));
                offsetProgAcademico++;
//                dbg(insert.toString());

            }
//            dbg(insert.toString());
            insert.flush();
        } catch (SQLException ex) {
            Logger.getLogger(CargaDatos.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private String generarDatosProgramasObj(IteradorDatos iterador, int offsetProgAcademico) throws SQLException {
        return String.format("(DEFAULT, '%s', '%s', %d, %d, %d, '%s', %b, '%s')",
                iterador.getString(1), iterador.getString(3), offsetProgAcademico,
                duracionSemestreProgramaAcademico(iterador.getInt(1)),
                totalCreditosProgramaAcademico(iterador.getInt(1)),
                nivelProgramaAcademico(iterador.getInt(1)),
                randomBool(), iterador.getString(2));
    }

    private int duracionSemestreProgramaAcademico(int codigo) {
        if (codigo < 2999) {
            return 7;
        } else {
            return 10;
        }

    }

    private int totalCreditosProgramaAcademico(int codigo) {
        if (codigo < 2999)//SERIA MEJOR CON UNA LISTA QUE SE SAQUE DE LA BASE
        {
            return 158;
        } else {
            return 10;
        }
    }

    private String nivelProgramaAcademico(int codigo) {
        if (codigo < 2999) {
            return "tecnología";
        } else {
            return "pregrado";
        }
    }

    private boolean randomBool() {
        return Math.round(Math.random() * 1) == 0;
    }

    private void cargarEstudiante() {
        try {
            IteradorDatos iterador = its.getIterador("ESTUDIANTES", its.SQL, "");

            insertarBD = conectarBD();
            BufferInsert insert = new BufferInsert(insertarBD.st, "INSERT INTO ESTUDIANTE "
                    + "(estudiante_k,codigo,nombres ,apellidos,"
                    + "numDocIdentidad,fechaNacimiento,añoIngreso,"
                    + " programa_acad,puestoIcfes,anhoIcfes,puntajeIcBiologia,"
                    + "puntajeIcLenguaje,puntajeIcMatematica,puntajeIcCien_Sociales,"
                    + "puntajeIcFilosofia ,puntajeIcQuimica ,puntajeIcFisica ,puntajeIcIngles)"
                    + " VALUES ");
            while (iterador.next()) {
//                dbg(generarDatosEstudiante(iterador,offsetProgAcademico));
                insert.append(generarDatosEstudiante(iterador, offsetProgAcademico));
//                offsetProgAcademico++;
//                dbg(insert.toString());

            }
//            dbg(insert.toString());
            insert.flush();
        } catch (SQLException ex) {
            Logger.getLogger(CargaDatos.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private String generarDatosEstudiante(IteradorDatos iterador, int offset) throws SQLException {
//        "INSERT INTO ESTUDIANTE "
//                    + "(estudiante_k,codigo,nombres ,apellidos,"
//                    + "numDocIdentidad,fechaNacimiento,añoIngreso,"
//                    + " programa_acad,puestoIcfes,anhoIcfes,puntajeIcBiologia,"
//                    + "puntajeIcLenguaje,puntajeIcMatematica,puntajeIcCien_Sociales,"
//                    + "puntajeIcFilosofia ,puntajeIcQuimica ,puntajeIcFisica ,puntajeIcIngles)"
//                    + " VALUES ");
        return String.format("(DEFAULT, '%s', '%s', '%s', '%s', '%s', %s, '%s', %s)",//por conveniencia se utilizo
                //enteros como %s string para no convertirlos
                iterador.getString(1), iterador.getString(4), apellidosEstudiante(iterador),
                iterador.getString(9), nacimientoEstudiante(iterador),
                anhoIngresoEstudiante(iterador), iterador.getString(2), icfes(iterador));
    }

    private String apellidosEstudiante(IteradorDatos it) throws SQLException {
        return it.getString(5) + " " + it.getString(6);
    }

    private String nacimientoEstudiante(IteradorDatos it) throws SQLException {
        double anhos = (14 + (Math.random() * 9));//fraccional osea con dias
        int dias = (int) (anhos * 365);//en "anhos"
        Date fecha = restarFechasDias(new Date(), dias);
        SimpleDateFormat formateador = new SimpleDateFormat("yyyy-MM-dd");
        return formateador.format(fecha);
    }

    //Restarle dias a una fecha determinada
    //@author  Henry Joe Wong Urquiza http://www.programandoconcafe.com/2011/03/java-manejo-de-fechas-javautildate.html
    //@param fch La fecha
    //@param dias Dias a restar
    //@return La fecha restando los dias
    public static java.sql.Date restarFechasDias(Date fch, int dias) {
        Calendar cal = new GregorianCalendar();
        cal.setTimeInMillis(fch.getTime());
        cal.add(Calendar.DATE, -dias);
        return new java.sql.Date(cal.getTimeInMillis());
    }

    private String anhoIngresoEstudiante(IteradorDatos it) throws SQLException {
        return it.getString(1).trim().substring(0, 4);
    }

    private String icfes(IteradorDatos it) throws SQLException {
//        puestoIcfes,anhoIcfes,puntajeIcBiologia,"
//                    + "puntajeIcLenguaje,puntajeIcMatematica,puntajeIcCien_Sociales,"
//                    + "puntajeIcFilosofia ,puntajeIcQuimica ,puntajeIcFisica ,puntajeIcIngles)"
        return String.format(" %d, %d, %d, %d, %d, %d, %d, %d, %d, %d", cienRandom(it),
                anhoIcfes(it), cienRandom(it), cienRandom(it), cienRandom(it), cienRandom(it),
                cienRandom(it), cienRandom(it), cienRandom(it), cienRandom(it));
    }

    private int anhoIcfes(IteradorDatos it) throws SQLException {
        return Integer.parseInt(anhoIngresoEstudiante(it)) - (int) Math.random() * 6;
    }

    private int cienRandom(IteradorDatos it) throws SQLException {
        return (int) (Math.random() * 100);
    }
    ConexionBD conexion;

    public IteradorDatos getIteradorSRA(String select) throws SQLException {
        if (conexion == null) {
            conexion = new ConexionBD("jdbc:postgresql://localhost:5432/SRA", "postgres", "postgres");
        }
        return its.getIteradorSelect(select, conexion, its.SQL);
    }

    private void cargarAsignatura() {
        try {
            IteradorDatos iterador = its.getIterador("ASIGNATURAS", its.SQL, "");

            insertarBD = conectarBD();
            BufferInsert insert = new BufferInsert(insertarBD.st, "INSERT INTO ASIGNATURA "
                    + "(asignatura_k,codigo,nombre,abreviacion "
                    + ",creditos,grupo,nivel ,tipoAsignatura,generico "
                    + ",anual ,habilitable,validable," //cuposProgramadosActual, se quito
                    + "ProfesorEncargado) VALUES ");
            String select = "SELECT "
                    + "DISTINCT asignaturas_estudiantes.grupo , asignaturas_estudiantes.codigoProgramaAcademico ,"
                    + "docentes.nombreDocente, docentes.responsable "
                    + "FROM public.asignaturas_estudiantes, public.docentes "
                    + "WHERE docentes.codigoDeAsignatura=asignaturas_estudiantes.codigoasignatura  AND "
                    + "docentes.grupo= asignaturas_estudiantes.grupo AND "
                    + "asignaturas_estudiantes.codigoasignatura = '";
//            dbg(select);
            
            insert.setMostrarErrores(false);

            String insertado = "";
            String actual = "";
            String datoInsertar = "";
            boolean nuevo = true;
            while (iterador.next()) {
//                dbg("codigo asign", iterador.getString(1));
//                 dbg(select+iterador.getString(1)+"' ORDER BY responsable DESC ");
                IteradorDatos iteradorGruop = getIteradorSRA(select + iterador.getString(1) + "' ORDER BY responsable DESC ");//primero los true los meta
                nuevo = true;
                while (iteradorGruop.next()) {
//                    dbg("grupo ",iteradorGruop.getString(1));
//                    dbg(generarDatosAsignaturaObj(iterador,iteradorGruop,offsetProgAcademico));
                    //102016M
                    insert.append(generarDatosAsignaturaObj(iterador, iteradorGruop, offsetProgAcademico));
                    insertado = iterador.getString(1) + iteradorGruop.getString(1);
                    nuevo = true;
                    datoInsertar = "";

//                    dbg(insert.toString());
                }
                insert.flush();

            }
//            dbg(insert.toString());
        } catch (SQLException ex) {
            Logger.getLogger(CargaDatos.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private String generarDatosAsignaturaObj(IteradorDatos it, IteradorDatos itGrup, int offset) throws SQLException {
//        asignatura_k,codigo,nombre,abreviacion "
//            + ",creditos,grupo,nivel ,tipoAsignatura,generico "
//            + ",anual ,habilitable,validable,cuposProgramadosActual,"
//            + "ProfesorEncargado                                                                          

        return String.format("(DEFAULT, '%s', '%s', '%s', %d, %d, '%s', '%s', %b, %b, %b, %b, %s)", it.getString(1),
                it.getString(2), it.getString(2),
                it.getInt(3), itGrup.getInt(1), nivelProgramaAcademico(itGrup.getInt(2)),
                tipoAsignatura(it, itGrup), randomBool(), randomBool(), randomBool(), randomBool(),
                /*cuposProgramados(it,itGrup),*/ profesorEncargado(it, itGrup));
    }

    private String tipoAsignatura(IteradorDatos it, IteradorDatos itgru) throws SQLException {
        String[] tipoAs = new String[]{"profesional", "básica", "electiva profesional"};
        return tipoAs[Math.round((float) (Math.random() * 2))];
    }

    private int cuposProgramados(IteradorDatos it, IteradorDatos itgru) throws SQLException {
        return (int) (18 + (Math.round(Math.random() * 42)));
    }

    private String profesorEncargado(IteradorDatos it, IteradorDatos itgru) throws SQLException {
        if (itgru.getString(4).equals("t")) {
            return String.format("'%s'", itgru.getString(3));
        }
        return "NULL";
    }

    private void cargarFecha() {
        try {
            cargarFechaAcciones("fechaMatricula");
            cargarFechaAcciones("fechaCancelacion");
            cargarFechaAcciones("fechaReactivacion");
        } catch (SQLException ex) {
            Logger.getLogger(CargaDatos.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void cargarFechaAcciones(String fecha) throws SQLException {
        IteradorDatos iterador = getIteradorSRA(String.format("SELECT DISTINCT EXTRACT (day FROM asignaturas_estudiantes.%s),"
                + "EXTRACT (month FROM asignaturas_estudiantes.%s),"
                + "EXTRACT (year FROM asignaturas_estudiantes.%s)"
                + "FROM public.asignaturas_estudiantes", fecha, fecha, fecha));
//        dbg(String.format("SELECT DISTINCT EXTRACT (day FROM asignaturas_estudiantes.%s),"
//                + "EXTRACT (month FROM asignaturas_estudiantes.%s),"
//                + "EXTRACT (year FROM asignaturas_estudiantes.%s)"
//                + "FROM public.asignaturas_estudiantes", fecha, fecha, fecha));
        insertarBD = conectarBD();
        BufferInsert insert = new BufferInsert(insertarBD.st, "INSERT INTO FECHA "
                + "(fecha_k,anho,semestre,"
                + "nombreSemestre,mes,nombreMes"
                + ",dia,nombreDia, numeroDiaSemana, festivo) VALUES ");
//        insert.setMostrarErrores(false);
        while (iterador.next()) {
//                dbg(generarDatosProgramasObj(iterador,offsetProgAcademico));
            if (iterador.getString(3) == null) {
                continue;
            }
            insert.append(generarDatosFechaObj(iterador));
//                dbg(insert.toString());

        }
//            dbg(insert.toString());
        insert.flush();
    }

    private String generarDatosFechaObj(IteradorDatos iterador) throws SQLException {
//INSERT INTO FECHA "
//                    + "(fecha_k,anho,semestre,"
//                    + "nombreSemestre,mes,nombreMes"
//                    + ",dia,,nombreDia, numeroDiaSemana,festivo)
        return String.format("(DEFAULT, %d, %d, '%s', %d, '%s', %d, '%s',%d, %s)",
                iterador.getInt(3), semestreFecha(iterador), nombreSemestreFecha(iterador),
                iterador.getInt(2), nombreMesFecha(iterador), iterador.getInt(1),
                nombrediaFecha(iterador), numeroDiaFecha(iterador),festivoFecha(iterador));
    }

    private int semestreFecha(IteradorDatos it) throws SQLException {
        if (it.getInt(2) < 7)//junio es 6
        {
            return 1;
        } else {
            return 2;
        }
    }

    private String nombreSemestreFecha(IteradorDatos it) throws SQLException {
        if (it.getInt(2) < 7)//junio es 6
        {
            return "Febrero-Junio-" + it.getString(3);
        } else {
            return "Agosto-Diciembre-" + it.getString(3);
        }
    }

    private String nombreMesFecha(IteradorDatos it) throws SQLException {
        String[] meses = new String[]{"enero", "febrero", "marzo", "abril",
            "mayo", "junio", "julio", "agosto", "septiembre",
            "octubre", "noviembre", "diciembre"};
        return meses[it.getInt(2) - 1];
    }

    private String nombrediaFecha(IteradorDatos it) throws SQLException {
        String[] dias = new String[]{"","domingo","lunes", "martes", "miercoles", "jueves",
            "viernes", "sabado"};
        Calendar fecha = new GregorianCalendar(it.getInt(3), it.getInt(2)-1, it.getInt(1));
        int diaSemana = fecha.get(Calendar.DAY_OF_WEEK);    // 6=Friday
        return dias[diaSemana];
    }
    
     private int numeroDiaFecha(IteradorDatos it) throws SQLException {
        Calendar fecha = new GregorianCalendar(it.getInt(3), it.getInt(2), it.getInt(1));
//        dbg(it.getInt(3), it.getInt(2), it.getInt(1));//TOOD:debugear
        int diaSemana = fecha.get(Calendar.DAY_OF_WEEK);    // 6=Friday
//        dbg("diaSemana",diaSemana);
        return diaSemana;
    }

    static HashSet<Point> festivos = new HashSet<Point>();

    static {
        festivos.add(new Point(1, 1));
        festivos.add(new Point(1, 9));
        festivos.add(new Point(2, 17));
        festivos.add(new Point(2, 18));
        festivos.add(new Point(3, 19));
        festivos.add(new Point(3, 30));
        festivos.add(new Point(4, 5));
        festivos.add(new Point(4, 6));
        festivos.add(new Point(4, 16));
        festivos.add(new Point(4, 22));
        festivos.add(new Point(5, 1));
        festivos.add(new Point(5, 4));
        festivos.add(new Point(5, 14));

        festivos.add(new Point(12, 1));
        festivos.add(new Point(12, 8));
        festivos.add(new Point(12, 10));
        festivos.add(new Point(12, 21));
        festivos.add(new Point(12, 25));
        //TODO: faltan festivos
    }

    private boolean festivoFecha(IteradorDatos it) throws SQLException {

        return festivos.contains(new Point(it.getInt(2), it.getInt(1)));
    }
    ConexionBD conexionMart;

    public IteradorDatos getIteradorMart(String select) throws SQLException {
        if (conexionMart == null) {
            conexionMart = new ConexionBD("jdbc:postgresql://localhost:5432/DataMartAcademico", "postgres", "postgres");
        }
        return its.getIteradorSelect(select, conexionMart, its.SQL);
    }

    private void cargarDemografico() {
        try {
            String select = "";
            IteradorDatos iterador = getIteradorMart("SELECT "
                    + "DISTINCT EXTRACT (year FROM estudiante.fechanacimiento)"
                    + "FROM "
                    + "public.estudiante;");

            insertarBD = conectarBD();
            BufferInsert insert = new BufferInsert(insertarBD.st, "INSERT INTO DEMOGRAFICOS "
                    + "(demograficos_k, edad, sexo, estadoCivil, "
                    + "estratoSocioE,colegioGraduando,tipoColegio,"
                    + "trabaja,personasACargo,numHermanos,escolaridadPadre "
                    + ",escolaridadMadre) VALUES ");
            while (iterador.next()) {
                insert.append(generarDatosEstudianteObj(iterador, "Ambos", offsetProgAcademico));
                insert.append(generarDatosEstudianteObj(iterador, "Masculino", offsetProgAcademico));
                insert.append(generarDatosEstudianteObj(iterador, "Femenino", offsetProgAcademico));
            }
//            dbg(insert.toString());
            insert.flush();
        } catch (SQLException ex) {
            Logger.getLogger(CargaDatos.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private String generarDatosEstudianteObj(IteradorDatos iterador, String sexo, int offset) throws SQLException {
//(demograficos_k, edad, sexo, estadoCivil, "
//                            + "estratoSocioE,colegioGraduando,tipoColegio,"
//                            + "trabaja,personasACargo,numHermanos,escolaridadPadre "
//                            + ",escolaridadMadre)
        int hermanos = numHermanos(iterador);
        String colegio = colegioGraduando(iterador);
        return String.format("(DEFAULT, %d, '%s', '%s', %d, '%s', '%s', %b, %d, %d, '%s', '%s')",
                edadEstudiante(iterador), sexo, estadoCivil(iterador), estratoSocioE(iterador), colegio,
                tipoColegio(iterador, colegio), randomBool(), personasACargo(iterador, hermanos), hermanos, escolaridadPadre(iterador), escolaridadMadre(iterador));
    }

    private int edadEstudiante(IteradorDatos iterador) throws SQLException {
        GregorianCalendar cal = new GregorianCalendar();
        return cal.get(GregorianCalendar.YEAR) - iterador.getInt(1);
    }

    private String estadoCivil(IteradorDatos iterador) throws SQLException {
        String[] estados = new String[]{"casado", "soltero", "union libre"};
        return estados[Math.round((float) (Math.random() * (estados.length - 1)))];
    }

    private int numHermanos(IteradorDatos iterador) throws SQLException {
        return Math.round((float) Math.random() * 5);
    }

    private int estratoSocioE(IteradorDatos iterador) throws SQLException {
        return Math.round((float) (Math.random() * 5)) + 1;//son hasta 6 sin 0
    }
    private String[] colegios = new String[]{"Colegio de Santa Librada", "Colegio de las Marianitas"};
    private String[] tiposColegios = new String[]{"publico", "privado"};

    private String colegioGraduando(IteradorDatos iterador) throws SQLException {
        return colegios[Math.round((float) (Math.random() * (colegios.length - 1)))];
    }

    private String tipoColegio(IteradorDatos iterador, String colegio) throws SQLException {
        int i = 0;
        for (; i < colegios.length; i++) {
            if (colegios[i].equals(colegio)) {
                break;
            }
        }
        return tiposColegios[i];
    }

    private int personasACargo(IteradorDatos iterador, int hermanos) throws SQLException {
        return hermanos + Math.round((float) (Math.random() * 6));//2 papas y 4 abuelos
    }

    private String escolaridadPadre(IteradorDatos iterador) throws SQLException {
        String[] escolaridadesP = new String[]{"Bachiller", "Profesional", "Sin padre", "Ténico", "Doctor", "No tiene"};
        return escolaridadesP[Math.round((float) (Math.random() * (escolaridadesP.length - 1)))];
    }

    private String escolaridadMadre(IteradorDatos iterador) throws SQLException {
        String[] escolaridadesP = new String[]{"Bachiller", "Profesional", "Sin madre", "Ténico", "Doctor", "No tiene"};
        return escolaridadesP[Math.round((float) (Math.random() * (escolaridadesP.length - 1)))];
    }

    private void cargarMatriculaYCancelaciones() {
        try {

            //            StringBuilder selectAsig=new StringBuilder("SELECT asignatura.asignatura_k,"
//                                        + " asignatura.codigo, asignatura.grupo "
//                                        + "FROM public.asignatura WHERE ");
//            for (int i = 0; i < 50; i++) {
//                if(!iteradorSRA.next())//acordarme aqui esta el next
//                    break;//hay que ponerlo a que saque mas arriba
//                if(i!=0)
//                    selectAsig.append(" OR \n");
//                
//                selectAsig.append(String.format("asignatura.codigo='%s' AND asignatura.grupo=%d ", iteradorSRA.getString(4),iteradorSRA.getInt(5)) );
//            } //paila lo devuelve en orden

//            IteradorDatos iteradorSRA=its.getIterador("ASIGNATURAS_ESTUDIANTES",its.SQL,"");//aqui van los 3 juntitos demole asi
            offsetMatriculas=offsetMatriculas();
            IteradorDatos iteradorSRA = getIteradorSRA("SELECT * FROM ASIGNATURAS_ESTUDIANTES ORDER BY codigoEstudiante OFFSET "+offsetMatriculas);
            insertarBD = conectarBD();
            
            BufferInsertMatriculas insert = new BufferInsertMatriculas(insertarBD.st, "INSERT INTO MATRICULA "
                    + "(tabulado_dd, fecha, hora, estudiante, "
                    + "programa,demografia,asignatura,"
                    + "locacion"
                    + ") VALUES ",7);
            BufferInsertMatriculas insertCancel = new BufferInsertMatriculas(insertarBD.st, "INSERT INTO CANCELACIONES "
                    + "(tabulado_dd, fecha, hora, estudiante, "
                    + "programa,demografia,asignatura,"
                    + "locacion"
                    + ") VALUES ",7);
            
            
//            BufferInsertMatriculas insert = new BufferInsertMatriculas(insertarBD.st, "INSERT INTO MATRICULA "
//                    + " VALUES ");
//            BufferInsertMatriculas insertCancel = new BufferInsertMatriculas(insertarBD.st, "INSERT INTO CANCELACIONES "
//                    + " VALUES ");
            
            IteradorDatos tmpLocacion = getIteradorMart("select count (locacion_k) from locacion");
            tmpLocacion.next();
            int cantLocacion = tmpLocacion.getInt(1);//iterar las locaciones
//            int cantLocacion=getIteradorMart("select count (locacion_k) from locacion").getInt(1);//iterar las locaciones


            String selectAsig ="SELECT asignatura.asignatura_k, "
                    + " asignatura.codigo, asignatura.grupo "
                    + "FROM public.asignatura WHERE ";

            String selectFecha ="SELECT fecha.fecha_k, "
                    + " anho, mes, dia "
                    + "FROM fecha WHERE ";
            String selectHora ="SELECT hora.hora_k,"
                    + " hora "
                    + "FROM hora WHERE ";
            String selectEstudiante ="SELECT estudiante.estudiante_k, "
                    + " estudiante.codigo, estudiante.fechaNacimiento "
                    + "FROM estudiante WHERE ";
            String selectPrograma ="SELECT programa_academico.programa_k, "
                    + " programa_academico.codigo "
                    + "FROM programa_academico WHERE ";
            String selectDemografia = "SELECT DEMOGRAFICOS.demograficos_k, "
                    + " edad,sexo "
                    + "FROM DEMOGRAFICOS WHERE ";
            String selectEstudianteSRA = "SELECT codigoEstudiante, "
                    + " genero "
                    + "FROM estudiantes WHERE ";
            String selectLocacion = "SELECT locacion.locacion_k, "
                    + " ipEquipo,espacio "
                    + "FROM locacion WHERE ";//entero
            int locacion = 0;



            while (iteradorSRA.next()/*&&*/) {
                offsetMatriculas++;
//                dbg(selectAsig+String.format
//                                                ("asignatura.codigo='%s' AND asignatura.grupo=%d ", iteradorSRA.getString(4),iteradorSRA.getInt(5)));

                IteradorDatos itAsignaturas = getIteradorMart(selectAsig + String.format("asignatura.codigo='%s' AND asignatura.grupo=%d ", iteradorSRA.getString(4), iteradorSRA.getInt(5)));

                IteradorDatos itEstudiante = getIteradorMart(selectEstudiante + String.format("codigo='%s' ",
                        iteradorSRA.getString(1)));

//                dbg(selectPrograma+String.format
//                                                ("codigo='%s' ", 
//                                                iteradorSRA.getString(2) ));

                IteradorDatos itPrograma = getIteradorMart(selectPrograma + String.format("codigo='%s' ",
                        iteradorSRA.getString(2)));
                IteradorDatos itEstudSRA = getIteradorSRA(selectEstudianteSRA + String.format("codigoEstudiante='%s' ",
                        iteradorSRA.getString(1)));
                itEstudSRA.next();
                itEstudiante.next();
//                dbg(selectDemografia+String.format
//                                                (" edad=%d AND sexo='%s'", 
//                                                edadFechaNacimiento(itEstudiante.getString(3)),
//                                                 itEstudSRA.getString(2)));
                IteradorDatos itDemografia = getIteradorMart(selectDemografia + String.format(" edad=%d AND sexo='%s' ORDER BY demograficos_k",
                        edadFechaNacimiento(itEstudiante.getString(3)),
                        itEstudSRA.getString(2)));
                locacion = (locacion + 1) % cantLocacion;
                IteradorDatos itLocacion = getIteradorMart(selectLocacion + String.format("locacion_k=%d ",
                        locacion));
                
                if (nextMultiple(itAsignaturas, itDemografia, itLocacion, itPrograma)) {
                    for (int acciones = 0; acciones < 3; acciones++) {//matricula, cancelcion, reactivacion
                        int anho = anhoFecha(iteradorSRA, acciones);
                        if (anho == -1) {
                            continue;
                        }
                        //                dbg(selectFecha+String.format
                        //                                                ("fecha.anho=%d AND fecha.mes=%d AND fecha.dia=%d ", 
                        //                                                anhoFecha(iteradorSRA,acciones),mesFecha(iteradorSRA,acciones),diaFecha(iteradorSRA,acciones)));
                        IteradorDatos itFecha = getIteradorMart(selectFecha + String.format("fecha.anho=%d AND fecha.mes=%d AND fecha.dia=%d ",
                                anho, mesFecha(iteradorSRA, acciones), diaFecha(iteradorSRA, acciones)));
                        //                dbg(selectHora+String.format
                        //                                                ("hora=%d ", 
                        //                                                horaFecha(iteradorSRA,acciones) ));

                        IteradorDatos itHora = getIteradorMart(selectHora + String.format("hora=%d ",
                                horaFecha(iteradorSRA, acciones)));
                        //                dbg(itAsignaturas.getString(1),itAsignaturas.getString(2),itAsignaturas.getString(3));
                        if (nextMultiple(itFecha, itHora)) {
                            if(acciones!=CANCELAR)
                                insert.append(generarDatosMatricula(itAsignaturas, itDemografia,
                                    itEstudSRA, itEstudiante, itFecha, itHora, itLocacion, itPrograma, iteradorSRA, acciones),
                                        itLocacion.getInt(1),itFecha.getInt(1),itHora.getInt(1),itPrograma.getInt(1), 
                                                                                    itAsignaturas.getInt(1),acciones,itEstudSRA.getString(2));
                            else
                                insertCancel.append(generarDatosMatricula(itAsignaturas, itDemografia,
                                    itEstudSRA, itEstudiante, itFecha, itHora, itLocacion, itPrograma, iteradorSRA, acciones),
                                        itLocacion.getInt(1),itFecha.getInt(1),itHora.getInt(1),
                                                                        itPrograma.getInt(1),itAsignaturas.getInt(1),acciones,itEstudSRA.getString(2));
                        }

                        //                itAsignaturas.next(); itDemografia.next(); itFecha.next(); itHora.next(); itLocacion.next(); 
                        //                itPrograma.next(); itEstudSRA.next();

                        //                itFecha.getInt(1);
                        //                itHora.getInt(1);
                        //                itEstudiante.getInt(1);
                        //                itPrograma.getInt(1); 
                        //                itDemografia.getInt(1);
                        //                itAsignaturas.getInt(1);
                        //                itLocacion.getInt(1);

                    }
                }
            }
//            dbg(insert.toString());
            insert.flush();
        } catch (SQLException ex) {
            Logger.getLogger(CargaDatos.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    final static int CANCELAR=1;
    final static int MATRICULAR=0;
    final static int REACTIVAR=2;
    
    private int anhoFecha(IteradorDatos it, int acciones) throws SQLException {
        String fecha = it.getString(7 + acciones);
        if (fecha == null) {
            return -1;
        }
        return Integer.parseInt(fecha.substring(0, 4));
    }

    private int mesFecha(IteradorDatos it, int acciones) throws SQLException {
        String fecha = it.getString(7 + acciones);
        return Integer.parseInt(fecha.substring(5, 7));
    }

    private int diaFecha(IteradorDatos it, int acciones) throws SQLException {
        String fecha = it.getString(7 + acciones);
        return Integer.parseInt(fecha.substring(8, 10));
    }

    private int horaFecha(IteradorDatos it, int acciones) throws SQLException {
        String fecha = it.getString(7 + acciones);
        return Integer.parseInt(fecha.substring(11, 13));
    }

    private int edadFechaNacimiento(String fecha) throws SQLException {
        GregorianCalendar cal = new GregorianCalendar();
        return cal.get(GregorianCalendar.YEAR) - Integer.parseInt(fecha.substring(0, 4));
    }

    private String generarDatosMatricula(IteradorDatos itAsignaturas, IteradorDatos itDemografia,
            IteradorDatos itEstudSRA, IteradorDatos itEstudiante, IteradorDatos itFecha,
            IteradorDatos itHora, IteradorDatos itLocacion, IteradorDatos itPrograma,
            IteradorDatos iteradorSRA, int acciones) throws SQLException {
//        "INSERT INTO MATRICULA "
//                    + "(tabualdo_dd, fecha, hora, estudiante, "
//                    + "programa,demografia,asignatura,"
//                    + "locacion,cancelo"
//                    + ") VALUES "
//        tabulado++;
//        dbg("generarDatosMatricula", iteradorSRA.getString(1), itEstudiante.getInt(1),itEstudiante.getString(2));
        return String.format("(%s, %d, %d, %d, %d, %d, %d, %d)", tabulado(iteradorSRA,acciones), itFecha.getInt(1), itHora.getInt(1),
                itEstudiante.getInt(1), itPrograma.getInt(1), itDemografia.getInt(1),
                itAsignaturas.getInt(1), itLocacion.getInt(1));
    }

    private long tabulado(IteradorDatos it, int acciones) throws SQLException {
//        String fecha = fechaFecha(it, acciones);
        //        Integer elo;
//        if (estudianteActualMatricula.equals(it.getString(1))) {
//            elo = diasTabulado.get(fecha);
//            if (elo == null)
//                diasTabulado.put(fecha, diasTabulado.size() + tabulado);
//
//        } else {
//            tabulado=diasTabulado.size() + tabulado;//el size incluye el ultimo metido, tonces el proximo es +1
//            estudianteActualMatricula=it.getString(1);
//            diasTabulado.clear();
//            diasTabulado.put(fecha, diasTabulado.size() + tabulado);
//            
//        }
//        elo = diasTabulado.get(fecha);
////        dbg(fecha,estudianteActualMatricula,elo);
//        return elo;
        
        String anho = it.getString(7 + acciones);
        long a= Integer.parseInt(anho.substring(0, 4));

        String mes = it.getString(7 + acciones);
        int m=Integer.parseInt(mes.substring(5, 7));

//        String dia = it.getString(7 + acciones);
//        long d= Integer.parseInt(dia.substring(8, 10));
        
        long semestre=0;
        if (m < 7)//junio es 6
        {
            semestre= 1;
        } else {
            semestre= 2;
        }
        
        semestre=semestre*10000;
        long aSemestre=a+semestre;
        aSemestre=aSemestre*1000000000;
        
        long codig=(it.getInt(1));
        
        long out=aSemestre+codig;//SUPERHASHCODE xD asi identifica unicamente 
                            //al codigo con la fecha del semestre inequivocamente siempre
        return out;
    }

    private boolean nextMultiple(Object... o) throws SQLException {
        boolean out = true;
        for (Object obj : o) {
            out = out && ((IteradorDatos) obj).next();
        }
        return out;
    }

//    private String cancelando(int acciones) {
//        return (acciones == 1) ? "TRUE" : "FALSE";
//    }

    private String fechaFecha(IteradorDatos it, int acciones) throws SQLException {
        String fecha = it.getString(7 + acciones);
        return fecha.substring(0, 10);
    }

    private int cargarTabulado() {
        String salida=Archivo.cargarDeArchivo("tabulado");
        if(salida.equals("")) return 0;
        return Integer.parseInt(salida);
    }

    private long diasFecha(IteradorDatos it, int acciones) throws SQLException {
        String anho = it.getString(7 + acciones);
        int a= Integer.parseInt(anho.substring(0, 4)); 
        a=a-1900;

        String mes = it.getString(7 + acciones);
        int m=Integer.parseInt(mes.substring(5, 7));

        String dia = it.getString(7 + acciones);
        int d= Integer.parseInt(dia.substring(8, 10));
        
        long out=d+(m*31)+(a*365);
        
        return out;
    }

    private int offsetProgAcademico() {
        String salida=Archivo.cargarDeArchivo(archProgAcademico);
        if(salida.equals("")) return 0;
        return Integer.parseInt(salida);
    }
    
    int offsetMatriculas;
    private int offsetMatriculas() {
        String salida=Archivo.cargarDeArchivo(archMatricula);
        if(salida.equals("")) return 0;
        return Integer.parseInt(salida);
    }
    
    final static String archProgAcademico="progAcademico";
    final static String archEstudiante="estudiante";
    final static String archMatricula="matricula";
    final static String archConfig="configuracion";
    
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.err.println("Guardando archivos");//ACORDARSE PONER TODOS LOS BERRACOS ARCHIVOS
        Archivo.guadarAArchivo(archConfig, "reiniciar= true");//TODO: QUITAR ANTES DE LA EXPO
        Archivo.guadarAArchivo(archProgAcademico, offsetProgAcademico+"");
        Archivo.guadarAArchivo(archEstudiante, ofEstudiante+"");
        Archivo.guadarAArchivo(archMatricula, offsetMatriculas+"");
    }

    private void reiniciar() throws IOException {
        String salida=Archivo.cargarDeArchivo(archConfig);
        if(salida.equals("")) return;
        dbg(salida);
        boolean reiniciar=Boolean.parseBoolean(salida.substring(11));
        if(reiniciar){
            Archivo.guadarAArchivo(archConfig, "reiniciar= true");
            Archivo.guadarAArchivo(archProgAcademico, 0+"");
            Archivo.guadarAArchivo(archEstudiante, 0+"");
            Archivo.guadarAArchivo(archMatricula, 0+"");
        }
    }

    private int randomInt(int i) {
        return (int) Math.round(Math.random()*i);
    }
    
}
